package com.example.test;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

public class AppStarter {

    //应用启动的端口
    private int port;

    //父类加载器
    private ClassLoader parentClassLoader;


    //静态应用类
    private String applicationClass;

    //业务类路径
    private List<File> businessClassPath;

    //开始应用
    public App start() {

        URL[] urls = new URL[businessClassPath.size()];

        for (int i = 0; i < businessClassPath.size(); i++) {
            try {
                urls[i] = businessClassPath.get(i).toURI().toURL();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        final App app = new App();

        final int fP = port;

        final ClassLoader fp = parentClassLoader;

        final String ac = applicationClass;

        //构建的的子上下文
        final URLClassLoader urlClassLoader = new URLClassLoader(urls, fp);

        //类加载器
        app.setClassLoader(urlClassLoader);

        Thread thread = new Thread(() -> {

            try {
                Class<?> AC = urlClassLoader.loadClass(ac);
                Class<?> SA = urlClassLoader.loadClass("org.springframework.boot.SpringApplication");
                Method run = SA.getDeclaredMethod("run", Class.class, String[].class);

                //上下文
                Object context = run.invoke(null, AC, new String[]{"--server.port=" + fP});

                //设置上下文
                app.setContext(context);
                app.setStatus(2);
            } catch (Exception e) {
                app.setStatus(3);
                app.setException(e);
            }


        });

        thread.setName("AppForPort-" + port);
        thread.setContextClassLoader(urlClassLoader);
        thread.start();
        app.setStatus(1);

        return app;
    }


    public void setBusinessClassPath(List<File> businessClassPath) {
        this.businessClassPath = businessClassPath;
    }

    public List<File> getBusinessClassPath() {
        return businessClassPath;
    }

    public ClassLoader getParentClassLoader() {
        return parentClassLoader;
    }

    public void setParentClassLoader(ClassLoader parentClassLoader) {
        this.parentClassLoader = parentClassLoader;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getApplicationClass() {
        return applicationClass;
    }

    public void setApplicationClass(String applicationClass) {
        this.applicationClass = applicationClass;
    }
}
